#pragma once

#include <windows.h>

namespace platform {

/**
 * Implements TLS using Win32 API only, to correctly
 * support threads which are not created with C++ runtime
 */
template<typename T>
class TlsNative
{
	volatile DWORD _slot;

	/**
	 * Helper function, stores a T* in TLS for
	 * current thread
	 */
	inline void _initThreadValue(T *pT) {
		::TlsSetValue(_slot, pT);
	}

public:
	/** Trivial constructor, the slot is not ready yet */
	inline TlsNative(void) : _slot(TLS_OUT_OF_INDEXES) {}

	/** should be called once on process start */
	inline void initSlot(void) { _slot = ::TlsAlloc(); }

	/** should be called once on process end */
	inline void releaseSlot(void) { ::TlsFree(_slot); }

	/** operators for accessing current thread's data */
	inline T * operator->(void) { return reinterpret_cast<T*>(::TlsGetValue(_slot)); }
	inline T & get(void) { return *(operator->()); }
	inline T & operator()(void) { return get(); }

	/**
	 * Initializes this thread's data using
	 * default constructor of T.
	 * Should be called once per thread
	 */
	inline void initThreadValue(void) {
		_initThreadValue(new T());
	}
	/**
	 * Initializes this thread's data using
	 * some constructor of T (usually
	 * P will be the same as T, but it's not a must)
	 * Should be called once per thread
	 */
	template<typename P>
	inline void initThreadValue(P val) {
		_initThreadValue(new T(val));
	}

	/**
	 * Releases the memory used by the object
	 * associated with current thread
	 */
	inline void releaseThreadValue(void) {
		delete &(get());
	}
};

typedef TlsNative<bool> TlsFlag;


}  // end namespace